{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "全0张量: tensor([[0., 0., 0.],\n",
      "        [0., 0., 0.]])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "torch.Size([3])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "zeros = torch.zeros(2, 3)\n",
    "print(\"全0张量:\", zeros)\n",
    "zeros[0].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 创建张量 ===\n",
      "从列表创建: tensor([1, 2, 3, 4])\n",
      "全0张量: tensor([[0., 0., 0.],\n",
      "        [0., 0., 0.]])\n",
      "全1张量: tensor([[1., 1., 1.],\n",
      "        [1., 1., 1.]])\n",
      "随机张量: tensor([[0.7061, 0.3047, 0.7225],\n",
      "        [0.0717, 0.5323, 0.7567]])\n",
      "未初始化张量: tensor([[4.8027e+01, 2.1076e-42, 3.0000e+00],\n",
      "        [4.0000e+00, 5.0000e+00, 6.0000e+00]])\n",
      "指定数据类型: tensor([1., 2., 3.], dtype=torch.float16)\n",
      "从NumPy创建: tensor([1, 2, 3], dtype=torch.int32)\n",
      "tensor_to_numpy: [1 2 3]\n",
      "\n",
      "=== 张量形状操作 ===\n",
      "原始张量形状: torch.Size([2, 3, 4])\n",
      "张量维度数: 3\n",
      "张量元素总数: 24\n",
      "重塑后形状: torch.Size([4, 6])\n",
      "展平后: torch.Size([24])\n",
      "维度扩展: torch.Size([1, 2, 3, 4])\n",
      "维度压缩: torch.Size([2, 4])\n",
      "\n",
      "=== 基础数学运算 ===\n",
      "加法: tensor([5., 7., 9.])\n",
      "减法: tensor([-3., -3., -3.])\n",
      "乘法: tensor([ 4., 10., 18.])\n",
      "除法: tensor([0.2500, 0.4000, 0.5000])\n",
      "矩阵乘法(3x2 @ 2x3): tensor([[ 27.,  30.,  33.],\n",
      "        [ 61.,  68.,  75.],\n",
      "        [ 95., 106., 117.]])\n",
      "求和: tensor(6.)\n",
      "平均值: tensor(2.)\n",
      "最大值: tensor(3.)\n",
      "最小值: tensor(1.)\n",
      "绝对值: tensor([1., 2., 3.])\n",
      "\n",
      "=== 索引与切片 ===\n",
      "原矩阵:\n",
      " tensor([[1, 2, 3],\n",
      "        [4, 5, 6],\n",
      "        [7, 8, 9]])\n",
      "第1行: tensor([1, 2, 3])\n",
      "第2列: tensor([2, 5, 8])\n",
      "子矩阵: tensor([[2, 3],\n",
      "        [5, 6]])\n",
      "matrix[[0,2], [1,2]] tensor([2, 9])\n",
      "选择特定行: tensor([[1, 2, 3],\n",
      "        [7, 8, 9]])\n",
      "布尔掩码索引: tensor([6, 7, 8, 9])\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "# 创建张量\n",
    "print(\"=== 创建张量 ===\")\n",
    "# 从列表创建\n",
    "x = torch.tensor([1, 2, 3, 4])\n",
    "print(\"从列表创建:\", x)\n",
    "\n",
    "# 创建全0张量\n",
    "zeros = torch.zeros(2, 3)\n",
    "print(\"全0张量:\", zeros)\n",
    "\n",
    "# 创建全1张量\n",
    "ones = torch.ones(2, 3)\n",
    "print(\"全1张量:\", ones)\n",
    "\n",
    "# 创建随机张量\n",
    "random_tensor = torch.rand(2, 3)\n",
    "print(\"随机张量:\", random_tensor)\n",
    "\n",
    "# 创建未初始化的张量\n",
    "empty_tensor = torch.empty(2, 3)\n",
    "print(\"未初始化张量:\", empty_tensor)\n",
    "\n",
    "# 指定数据类型\n",
    "float_tensor = torch.tensor([1, 2, 3], dtype=torch.float16)\n",
    "print(\"指定数据类型:\", float_tensor)\n",
    "\n",
    "# 从NumPy数组创建\n",
    "np_array = np.array([1, 2, 3])\n",
    "tensor_from_np = torch.from_numpy(np_array)\n",
    "print(\"从NumPy创建:\", tensor_from_np)\n",
    "print('tensor_to_numpy:', tensor_from_np.numpy())\n",
    "\n",
    "\n",
    "# 形状操作\n",
    "print(\"\\n=== 张量形状操作 ===\")\n",
    "tensor = torch.rand(2, 3, 4)\n",
    "print(\"原始张量形状:\", tensor.shape)\n",
    "print(\"张量维度数:\", tensor.dim())\n",
    "print(\"张量元素总数:\", tensor.numel())\n",
    "\n",
    "# 形状变换\n",
    "reshaped = tensor.reshape(4, 6)\n",
    "print(\"重塑后形状:\", reshaped.shape)\n",
    "print(\"展平后:\", tensor.flatten().shape)\n",
    "print(\"维度扩展:\", tensor.unsqueeze(0).shape)  # 在第0维添加维度\n",
    "print(\"维度压缩:\", tensor[:, 0:1, :].squeeze(1).shape)  # 压缩大小为1的维度\n",
    "\n",
    "# 数学运算\n",
    "print(\"\\n=== 基础数学运算 ===\")\n",
    "a = torch.tensor([1, 2, 3], dtype=torch.float32)\n",
    "b = torch.tensor([4, 5, 6], dtype=torch.float32)\n",
    "print(\"加法:\", a + b)\n",
    "print(\"减法:\", a - b)\n",
    "print(\"乘法:\", a * b)  # 元素级乘法\n",
    "print(\"除法:\", a / b)\n",
    "\n",
    "# 更多数学操作\n",
    "# 创建3行2列和2行3列的tensor\n",
    "tensor_3x2 = torch.tensor([[1, 2], [3, 4], [5, 6]], dtype=torch.float32)\n",
    "tensor_2x3 = torch.tensor([[7, 8, 9], [10, 11, 12]], dtype=torch.float32)\n",
    "# 执行矩阵乘法\n",
    "print(\"矩阵乘法(3x2 @ 2x3):\", torch.matmul(tensor_3x2, tensor_2x3))\n",
    "print(\"求和:\", a.sum())\n",
    "print(\"平均值:\", a.mean())\n",
    "print(\"最大值:\", a.max())\n",
    "print(\"最小值:\", a.min())\n",
    "print(\"绝对值:\", a.abs())\n",
    "# print(\"形状变化后的元素级乘法:\", tensor_3x2 * tensor_2x3)\n",
    "\n",
    "# 索引和切片\n",
    "print(\"\\n=== 索引与切片 ===\")\n",
    "matrix = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
    "print(\"原矩阵:\\n\", matrix)\n",
    "print(\"第1行:\", matrix[0])\n",
    "print(\"第2列:\", matrix[:, 1])\n",
    "print(\"子矩阵:\", matrix[0:2, 1:3])\n",
    "print('matrix[[0,2], [1,2]]',matrix[[0,2], [1,2]])\n",
    "\n",
    "# 高级索引\n",
    "indices = torch.tensor([0, 2])\n",
    "print(\"选择特定行:\", matrix[indices])\n",
    "mask = matrix > 5\n",
    "print(\"布尔掩码索引:\", matrix[mask])\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== 张量与常量运算 ===\n",
      "张量加常量: tensor([[11., 12., 13.],\n",
      "        [14., 15., 16.]])\n",
      "张量乘常量: tensor([[10., 20., 30.],\n",
      "        [40., 50., 60.]])\n",
      "\n",
      "=== 广播机制 ===\n",
      "张量A形状: torch.Size([2, 3])\n",
      "张量B形状: torch.Size([1, 3])\n",
      "张量相加 (广播):\n",
      " tensor([[11., 22., 33.],\n",
      "        [14., 25., 36.]])\n",
      "张量C形状: torch.Size([2, 1])\n",
      "张量A与C相乘 (广播):\n",
      " tensor([[ 1.,  2.,  3.],\n",
      "        [ 8., 10., 12.]])\n"
     ]
    }
   ],
   "source": [
    "# 张量与常量运算\n",
    "print(\"\\n=== 张量与常量运算 ===\")\n",
    "tensor_2d = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)\n",
    "constant = 10\n",
    "print(\"张量加常量:\", tensor_2d + constant)\n",
    "print(\"张量乘常量:\", tensor_2d * constant)\n",
    "\n",
    "# 广播机制 - 不同形状的张量运算\n",
    "print(\"\\n=== 广播机制 ===\")\n",
    "tensor_a = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32)  # 形状为 (2, 3)\n",
    "tensor_b = torch.tensor([[10, 20, 30]], dtype=torch.float32)         # 形状为 (1, 3)\n",
    "print(\"张量A形状:\", tensor_a.shape)\n",
    "print(\"张量B形状:\", tensor_b.shape)\n",
    "print(\"张量相加 (广播):\\n\", tensor_a + tensor_b)\n",
    "\n",
    "# 另一个广播例子\n",
    "tensor_c = torch.tensor([[1], [2]], dtype=torch.float32)             # 形状为 (2, 1)\n",
    "print(\"张量C形状:\", tensor_c.shape)\n",
    "print(\"张量A与C相乘 (广播):\\n\", tensor_a * tensor_c)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n"
     ]
    }
   ],
   "source": [
    "print(torch.Tensor([1]).item()) #获取一个tensor中的元素值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t2.shape (1, 1, 2)\n",
      "[[3]\n",
      " [4]]\n",
      "--------------------------------------------------\n",
      "id(t2)=2789149344272,id(b)=2789146482928\n",
      "[[100]\n",
      " [  4]]\n",
      "[[[100   4]]]\n"
     ]
    }
   ],
   "source": [
    "t2 =np.array([[[3,4]]])\n",
    "print('t2.shape',t2.shape)\n",
    "b=t2.reshape([2, -1]) # -1表示自动计算\n",
    "print(b)\n",
    "print('-'*50)\n",
    "print(f'id(t2)={id(t2)},id(b)={id(b)}') #t2的形状并没有发生改变\n",
    "b[0][0] = 100\n",
    "print(b)\n",
    "print(t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t2.shape torch.Size([1, 1, 2])\n",
      "tensor([[3.],\n",
      "        [4.]])\n",
      "--------------------------------------------------\n",
      "id(t2)=2788251983120,id(b)=2789177726992\n"
     ]
    }
   ],
   "source": [
    "t2 = torch.Tensor([[[3,4]]])\n",
    "print('t2.shape',t2.shape)\n",
    "b=t2.view([2, -1]) # -1表示自动计算\n",
    "print(b)\n",
    "print('-'*50)\n",
    "print(f'id(t2)={id(t2)},id(b)={id(b)}') #t2的形状并没有发生改变"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[100.],\n",
      "        [  4.]])\n",
      "tensor([[[100.,   4.]]])\n"
     ]
    }
   ],
   "source": [
    "b[0][0] = 100\n",
    "print(b)\n",
    "print(t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t2.untyped_storage().untyped().data_ptr() == b.untyped_storage().untyped().data_ptr() #判断两个tensor是否共享内存"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 运算函数加下划线与不加的区别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始张量 a: tensor([10, 20, 30])\n",
      "新张量 c = a.sub(b): tensor([ 9, 18, 27])\n",
      "a  tensor([10, 20, 30])\n",
      "--------------------------------------------------\n",
      "执行 a.sub_(b) 后的 a: tensor([ 9, 18, 27])\n",
      "原地操作后 a 已被修改\n"
     ]
    }
   ],
   "source": [
    "# 不带下划线的方法（sub）返回一个新的张量，不会修改原始张量\n",
    "a = torch.tensor([10, 20, 30])\n",
    "b = torch.tensor([1, 2, 3])\n",
    "c = a.sub(b)  # 等价于 c = a - b\n",
    "\n",
    "print(\"原始张量 a:\", a)\n",
    "print(\"新张量 c = a.sub(b):\", c)\n",
    "print(\"a \",a)\n",
    "\n",
    "print(\"-\" * 50)\n",
    "\n",
    "# 带下划线的方法（sub_）会直接修改原始张量（即原地操作）\n",
    "a = torch.tensor([10, 20, 30])\n",
    "b = torch.tensor([1, 2, 3])\n",
    "a.sub_(b)  # 等价于 a -= b\n",
    "\n",
    "print(\"执行 a.sub_(b) 后的 a:\", a)\n",
    "print(\"原地操作后 a 已被修改\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
